<!--下拉树选择组件-->
<template>
  <a-form-item :label="label">
    <a-tree-select
        dropdownClassName="c-form-select-dropdown"
        v-decorator="vDecorator"
        :style="getStyle"
        :placeholder="!isDisabled ? cplaceholder : ''"
        :treeData="dataSoure"
        :disabled="isDisabled"
        :allowClear="allowClear"
        :maxTagCount="maxTagCount"
        :multiple="multiple"
        :maxTagPlaceholder="maxTagPlaceholder"
        :treeCheckable="treeCheckableFlag"
        :showSearch="showSearch"
        :treeNodeFilterProp="treeNodeFilterProp"
        :dropdownStyle="{ maxHeight, overflow: 'auto' }"
        @change="onChange"
    ></a-tree-select>
  </a-form-item>
</template>

<script>
import { mixin } from './js/form.js'

export default {
  name: 'AntFormTreeSelect',
  mixins: [mixin],
  props: {
    /**
     * 是否禁用
     */
    disabled: {
      type: Boolean,
      default: false
    },
    /**
     * 是否由form表单自动布局
     */
    autoLayoutByForm: {
      type: Boolean,
      default: true
    },
    /**
     * 显示文本
     */
    label: {
      type: String,
      default: ''
    },
    /**
     * 输入提示
     */
    placeholder: {
      type: String,
      default: ''
    },
    /**
     * 最多显示多少个tag
     */
    maxTagCount: {
      type: Number,
      default: 0
    },
    /**
     * 是否多选
     */
    multiple: {
      type: Boolean,
      default: false
    },
    /**
     * 显示 checkbox，当设置为true时 multiple 时自动变为 true）
     */
    treeCheckable: {
      type: Boolean,
      default: false
    },
    /**
     * 最大高度
     */
    maxHeight: {
      type: String,
      default: '400px'
    },
    /**
     * 下拉数据源，接口url或数组
     */
    treeData: {
      type: [Array, String],
      default: () => []
    },
    /**
     * 绑定字段 ['phone' ,{ rules: [{ required: true},{validator:function(rule, value, callback)] }],自定义验证方法时callback回调函数必须在方法中调用，
     * 失败返回错误提示callback("xxx")，成功返回callback()
     * 字段值多个逗号隔开
     */
    vDecorator: {
      type: Array,
      default: () => []
    },
    /**
     * 允许清除选择数据
     */
    allowClear: {
      type: Boolean,
      default: true
    },
    /**
     * 是否在下拉中显示搜索框(仅在单选模式下生效)
     */
    showSearch: {
      type: Boolean,
      default: false
    },
    /**
     * 最大显示长度
     */
    maxLength: {
      type: Number,
      default: 15
    },
    /**
     * css样式，优先级最高
     */
    cstyle: {
      type: String,
      default: ''
    },
    /**
     * 非自动布局的宽度，优先级最低
     */
    defaultWidth: {
      type: Number,
      default: 240
    }
  },
  data() {
    return {
      //是否禁用和输入提示，由AntForm组件调用
      cdisabled: false,
      cplaceholder: this.placeholder ? this.placeholder : '请选择' + this.label,
      dataSoure: [],
      // 初始化完成标志，因为url是异步加载
      initFlag: false,
      treeCheckableFlag: this.treeCheckable,
      treeNodeFilterProp: this.treeCheckable ? (this.showSearch ? 'title' : '') : 'title',
      defaultValue: null
    }
  },
  computed: {
    /**
     * 获取样式
     */
    getStyle() {
      return { width: (this.percentageLayoutWidth ? this.percentageLayoutWidth : this.defaultWidth) + 'px', ...this.cstyle }
    }
  },
  created() {
  },
  mounted() {
    this.loadData(this.treeData)
    // 自动添加验证为空时的message
    let vDecorator = this.vDecorator
    if (vDecorator.length > 1 && vDecorator[1].rules) {
      let rules = vDecorator[1].rules
      rules.forEach((obj) => {
        if (obj.required && !obj.message) {
          obj.message = '请选择' + this.label
        }
      })
    }
  },
  watch: {
    treeData(val) {
      this.loadData(val)
    }
  },
  beforeDestroy() {
  },
  methods: {
    /**
     * 加载数据源
     * @param val
     */
    loadData(val) {
      if (val instanceof Array) {
        this.dataSoure = val
        this.initFlag = true
      } else {
        this.$getAction(val, {}).then((res) => {
          this.dataSoure = res.data
          this.initFlag = true
          this.defaultValue = this.dataSoure[0].value
          // 数据加载就绪回调
          this.$emit('initDataReady', this.dataSoure)
        })
      }
    },
    /**
     * 选择数据发生改变事件
     * @param val
     * @param label
     */
    onChange(val, label) {
      this.$nextTick(() => {
        this.$emit('change', val, label)
      })
    },
    /**
     * 隐藏 tag 时显示的内容
     * @param omittedValues
     * @returns {*}
     */
    maxTagPlaceholder(omittedValues) {
      const dataSource = this.dataSoure
      const selectLists = this.list(dataSource, omittedValues)
      // 扁平化处理结果，并过滤掉undefined
      const data = []
      selectLists.forEach((item) => {
        if (item && typeof item === 'string') {
          data.push(item)
        } else if (Array.isArray(item)) {
          item.forEach((subItem) => {
            if (subItem && typeof subItem === 'string') {
              data.push(subItem)
            }
          })
        }
      })
      return (
          <a-popover overlayStyle={{ width: '300px' }}>
            <template v-slot:content>{data.join(',')}</template>
            <div class="hidden">
              {data.join(',').length > this.maxLength
                  ? data.join(',').substring(0, this.maxLength) + '...'
                  : data.join(',')}
            </div>
          </a-popover>
      )
    },
    list(list1, omittedValues) {
      return list1.map((item) => {
        if (omittedValues.indexOf(item.value) > -1) {
          return item.title // 直接返回完整的title字符串
        } else {
          if (item.children && item.children.length) {
            return this.list(item.children, omittedValues)
          }
        }
        return undefined
      })
    },
    /**
     * 赋值之前的转换操作,由AntForm组件自动调用
     * 参数：recordPara，转换之前的record
     * 返回值：转换之后的可用于赋值的对象
     */
    beforeSetValue(recordPara) {
      let record = {}
      let key = this.vDecorator[0]
      let val = recordPara[key]
      if (this.multiple) {
        if (val) {
          val = val.split(',')
        } else {
          val = []
        }
      }
      record[key] = val
      this.selectValue = val
      return record
    },
    /**
     * 取值之前的转换操作,由AntForm组件自动调用
     * 参数：recordPara，转换之前的record
     * 返回值：转换之后的对象
     */
    beforeGetValue(recordPara) {
      let record = {}
      let key = this.vDecorator[0]
      let val = recordPara[key]
      if (val && this.multiple) {
        val = val.join(',')
      }
      record[key] = val
      return record
    }
  }
}
</script>

<style lang="less" scoped>
::v-deep .ant-select-selection.ant-select-selection--multiple {
  height: 33px !important;
  overflow: auto !important;
}

::v-deep .ant-input:hover,
::v-deep .ant-input:focus {
  border-color: #1a67f8;
}
</style>
